#!/usr/bin/env python3
#-*- coding:utf8 -*-
# Power by 2020-06-01 22:47:20

import paddle
import paddle.fluid as fluid
import paddle.fluid.dygraph as dygraph
from paddle.fluid.dygraph import Linear
import numpy as np
import os
import random

def load_data():
    # 从文件导入数据
    datafile = './housing.data'
    data = np.fromfile(datafile, sep=' ')

    # 每条数据包括14项，其中前面13项是影响因素，第14项是相应的房屋价格中位数
    feature_names = [ 'CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', \
                      'DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT', 'MEDV' ]
    feature_num = len(feature_names)

    # 将原始数据进行Reshape，变成[N, 14]这样的形状
    data = data.reshape([data.shape[0] // feature_num, feature_num])

    # 将原数据集拆分成训练集和测试集
    # 这里使用80%的数据做训练，20%的数据做测试
    # 测试集和训练集必须是没有交集的
    ratio = 0.8
    offset = int(data.shape[0] * ratio)
    training_data = data[:offset]

    # 计算train数据集的最大值，最小值，平均值
    maximums, minimums, avgs = training_data.max(axis=0), training_data.min(axis=0), \
                                 training_data.sum(axis=0) / training_data.shape[0]

    # 记录数据的归一化参数，在预测时对数据做归一化
    global max_values
    global min_values
    global avg_values
    max_values = maximums
    min_values = minimums
    avg_values = avgs

    # 对数据进行归一化处理
    for i in range(feature_num):
        #print(maximums[i], minimums[i], avgs[i])
        data[:, i] = (data[:, i] - avgs[i]) / (maximums[i] - minimums[i])

    # 训练集和测试集的划分比例
    #ratio = 0.8
    #offset = int(data.shape[0] * ratio)
    training_data = data[:offset]
    test_data = data[offset:]
    return training_data, test_data
class Regressor(fluid.dygraph.Layer):

    """network"""

    def __init__(self):
        """TODO: to be defined.

        :inputs: TODO

        """
        super(Regressor,self).__init__()
        self.fc=Linear(input_dim=13,output_dim=1,act=None)
    def forward(self,inputs):
        x=self.fc(inputs)
        return x
with fluid.dygraph.guard():
    model=Regressor()
    model.train()
    training_data,test_data=load_data()
    opt=fluid.optimizer.SGD(learning_rate=0.01,parameter_list=model.parameters())
with dygraph.guard(fluid.CPUPlace()):
    EPOCH_NUM=10
    BATCH_SIZE=10
    for epoch_id in range(EPOCH_NUM):
        np.random.shuffle(training_data)
        mini_batches=[training_data[k:k+BATCH_SIZE] for k in range(0,len(training_data),BATCH_SIZE)]
        for iter_id,mini_batch in enumerate(mini_batches):
            x=np.array(mini_batch[:,:-1]).astype('float32')
            y=np.array(mini_batch[:,-1:]).astype('float32')
            house_features=dygraph.to_variable(x)
            prices=dygraph.to_variable(y)
            predicts=model(house_features)
            loss=fluid.layers.square_error_cost(predicts,label=prices)
            avg_loss=fluid.layers.mean(loss)
            #if iter_id%20==0:
                #print("epoch: {}, iter: {}, loss is: {}".format(epoch_id, iter_id, avg_loss.numpy()))
            avg_loss.backward()
            opt.minimize(avg_loss)
            model.clear_gradients()
    fluid.save_dygraph(model.state_dict(),'LR_model')
def load_one_example(data_dir):
    f=open(data_dir,'r')
    datas=f.readlines()
    tmp=datas[-10]
    tmp=tmp.strip().split()
    one_data=[float(v) for v in tmp]
    for i in range(len(one_data)-1):
        one_data[i]=(one_data[i] - avg_values[i]) / (max_values[i] - min_values[i])
    data=np.reshape(np.array(one_data[:-1]),[1,-1]).astype(np.float32)
    label=one_data[-1]
    return data,label
with dygraph.guard():
    model_dict,_=fluid.load_dygraph('LR_model')
    model.load_dict(model_dict)
    model.eval()

    test_data,label=load_one_example('./housing.data')
    test_data=dygraph.to_variable(test_data)
    results=model(test_data)
    results=results*(max_values[-1] - min_values[-1]) + avg_values[-1]
    print("Inference result is {}, the corresponding label is {}".format(results.numpy(), label))



